package com.icode.service.impl.house;

import com.icode.core.dto.house.*;
import com.icode.core.dto.manager.AssignmentDTO;
import com.icode.core.model.house.*;
import com.icode.core.shared.HouseBaseHandle;
import com.icode.core.shared.ImageUtils;
import com.icode.dao.HouseDao;
import com.icode.dao.HouseWeekDao;
import com.icode.service.house.HouseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 * User: SunKai
 * Date: 14-11-5
 * Time: 上午11:03
 * To change this template use File | Settings | File Templates.
 */
@Service("houseService")
@PropertySource("classpath:database.properties")
@Transactional
public class HouseServiceImpl implements HouseService {

    @Autowired
    private HouseDao houseDao;

    @Autowired
    private HouseWeekDao houseWeekDao;

    @Override
    @Transactional
    public void saveOrUpdateEquipment(EquipmentDTO equipmentDTO, EquipmentType type) {
        String guid = equipmentDTO.getGuid();
        if (StringUtils.isEmpty(guid)) {
            Equipment equipment = equipmentDTO.toEquipments(type);
            houseDao.saveOrUpdate(equipment);
        } else {
            houseDao.saveOrUpdateEquipmentByGuid(equipmentDTO);
        }
    }


    @Override
    @Transactional
    public List<EquipmentDTO> getEquipmentDTOs(EquipmentType type) {
        List<Equipment> equipments = houseDao.findEquipmentsByType(type);
        return EquipmentDTO.toDTOs(equipments);
    }


    @Override
    @Transactional
    public EquipmentDTO getEquipmentByGuid(String guid) {
        Equipment equipment = houseDao.findByGuid(Equipment.class, guid);
        return EquipmentDTO.toDTO(equipment);
    }

    @Override
    @Transactional
    public void deleteEquipmentByGuid(String guid) {
        houseDao.deleteByLogic(false, guid);
    }

    @Override
    @Transactional
    public void saveOrUpdateHouse(HouseInfoDTO houseInfoDTO) {
        List<String> imageGuids = houseInfoDTO.getImageGuids();
        List<UploadImage> documents = houseDao.findByGuids(UploadImage.class, imageGuids);
        List<String> equipmentAsStrings = houseInfoDTO.getEquipmentAsStrings();
        List<String> supportingAsStrings = houseInfoDTO.getSupportingAsStrings();
        List<Equipment> equipments = new ArrayList<>();
        if (equipmentAsStrings != null) {
            equipments = houseDao.findByGuids(Equipment.class, equipmentAsStrings);
        }
        List<Equipment> supportings = new ArrayList<>();
        if (supportingAsStrings != null) {
            supportings = houseDao.findByGuids(Equipment.class, supportingAsStrings);
        }
        BuildingType buildingType = houseDao.findByGuid(BuildingType.class, houseInfoDTO.getBuildingTypeGuid());
        HouseInfo houseInfo = null;
        String guid = houseInfoDTO.getGuid();
        if (!StringUtils.isEmpty(guid)) {
            HouseInfo houseInfoFound = houseDao.findByGuid(HouseInfo.class, guid);
            houseDao.deleteHouserhouseInfoImages(houseInfoFound);
            houseInfo = houseInfoDTO.toHouseInfo(equipments, supportings, documents, buildingType, houseInfoFound);
        } else {
            houseInfo = houseInfoDTO.toHouseInfo(equipments, supportings, documents, buildingType);
        }

        houseDao.saveOrUpdate(houseInfo);

        String content = houseInfoDTO.getContent();
        String houseInfoGuid = houseInfo.guid();
        AgreementDTO agreementDTO = new AgreementDTO(houseInfo, content, houseInfoGuid);
        saveOrUpdateAgreement(agreementDTO);

    }
//    @Override
//    @Transactional
//    public void saveOrUpdateHouse(HouseInfoDTO houseInfoDTO) {
//        List<MultipartFile> list = houseInfoDTO.getImages();
//        List<UploadImage> documents = new ArrayList<>();
//        if (!list.get(0).isEmpty()) {
//            documents = ImageUtils.resolveUploadImages(list);
//        }
//        List<String> equipmentAsStrings = houseInfoDTO.getEquipmentAsStrings();
//        List<String> supportingAsStrings = houseInfoDTO.getSupportingAsStrings();
//        List<Equipment> equipments = new ArrayList<>();
//        if (equipmentAsStrings != null) {
//            equipments = houseDao.findByGuids(Equipment.class, equipmentAsStrings);
//        }
//        List<Equipment> supportings = new ArrayList<>();
//        if (supportingAsStrings != null) {
//            supportings = houseDao.findByGuids(Equipment.class, supportingAsStrings);
//        }
//        BuildingType buildingType = houseDao.findByGuid(BuildingType.class, houseInfoDTO.getBuildingTypeGuid());
//        HouseInfo houseInfo = null;
//        String guid = houseInfoDTO.getGuid();
//        if (!StringUtils.isEmpty(guid)) {
//            HouseInfo houseInfoFound = houseDao.findByGuid(HouseInfo.class, guid);
//            houseInfo = houseInfoDTO.toHouseInfo(equipments, supportings, documents, buildingType, houseInfoFound);
//        } else {
//            houseInfo = houseInfoDTO.toHouseInfo(equipments, supportings, documents, buildingType);
//        }
//
//        houseDao.saveOrUpdate(houseInfo);
//
//        String content = houseInfoDTO.getContent();
//        String houseInfoGuid = houseInfo.guid();
//        AgreementDTO agreementDTO = new AgreementDTO(houseInfo, content, houseInfoGuid);
//        saveOrUpdateAgreement(agreementDTO);
//
//    }

    @Override
    @Transactional
    public List<HouseInfoDTO> getHouseInfoDTOs() {
        List<HouseInfo> houseInfoList = houseDao.findAll(HouseInfo.class);
        return HouseInfoDTO.toDTOs(houseInfoList);
    }

    @Override
    @Transactional
    public HouseInfoDTO findHouseInfoByBuildingTypeGuid(String buildingTypeGuid) {
        List<HouseInfo> houseInfos = houseDao.findHouseInfoByBuildingType(buildingTypeGuid);
        HouseInfoDTO houseInfoDTO = new HouseInfoDTO();
        if (!houseInfos.isEmpty()) {
            houseInfoDTO = HouseInfoDTO.toDTO(houseInfos.get(0));
        }
        return houseInfoDTO;
    }

    @Override
    @Transactional
    public byte[] getImageByGuid(String guid) {
        UploadImage uploadImage = houseDao.findByGuid(UploadImage.class, guid);
        return uploadImage.getContents();
    }

    @Override
    @Transactional
    public void saveOrUpdateBuildingType(BuildingTypeDTO buildingTypeDTO) throws IOException {
        if ("".equals(buildingTypeDTO.getGuid())) {  //新增
            String houseBaseGuid = buildingTypeDTO.getHouseBaseGuid();
            HouseBase houseBase = houseDao.findByGuid(HouseBase.class, houseBaseGuid);
            BuildingType buildingType = buildingTypeDTO.toBuildingType(houseBase);
            houseDao.saveOrUpdate(buildingType);
        } else {  //更新
            BuildingType buildingType = houseDao.findBuildingTypeByGuid(buildingTypeDTO.getGuid());
            String houseBaseGuid = buildingTypeDTO.getHouseBaseGuid();
            HouseBase houseBase = houseDao.findByGuid(HouseBase.class, houseBaseGuid);
            buildingType = buildingTypeDTO.toBuildingTypeForUpdate(buildingType, houseBase);
            houseDao.saveOrUpdate(buildingType);
        }
    }

    @Override
    @Transactional
    public List<BuildingTypeDTO> getBuildingTypeDTOsByBaseGuid(String baseGuid) {
        HouseBase houseBase = houseDao.findByGuid(HouseBase.class, baseGuid);
        List<BuildingType> buildingTypes = houseBase.buildingTypes();
        return BuildingTypeDTO.toDTOs(buildingTypes);
    }

    @Override
    @Transactional
    public HouseInfoDTO getHouseInfoByGuid(String guid) {
        HouseInfo houseInfo = houseDao.findByGuid(HouseInfo.class, guid);
        return HouseInfoDTO.toDTO(houseInfo);
    }

    @Override
    @Transactional
    public HouseWeekDTO findHouseWeekByGuid(String guid) {
        HouseWeek houseWeek = houseDao.findByGuid(HouseWeek.class, guid);
        return HouseWeekDTO.toDTO(houseWeek);
    }


    @Override
    @Transactional
    public void saveOrUpdateHouseBase(HouseBaseDTO houseBaseDTO) {
        HouseBase houseBase = houseBaseDTO.toHouseBase(houseBaseDTO.getImages());
        houseDao.saveOrUpdateHouseBase(houseBase);
    }

    @Override
    @Transactional
    public void saveOrUpdateHouseBaseByGuid(HouseBaseDTO houseBaseDTO, String guid) {
        List<MultipartFile> list = houseBaseDTO.getImages();
        HouseBase findhouseBase = houseDao.findByGuid(HouseBase.class, guid);
        List<HouseBaseImage> findUploadImage = findhouseBase.houseBaseImages();
        if (!"".equals(list.get(0).getOriginalFilename())) { //上传了图片
            HouseBase houseBase = houseBaseDTO.toHouseBase(houseBaseDTO);
            houseBase.addHouseBaseImage(findUploadImage);
            houseBase.setId(Integer.parseInt(houseBaseDTO.getId()));
            houseDao.saveOrUpdateHouseBaseByGuid(houseBase, guid);
        } else {
            HouseBase houseBase = houseBaseDTO.toHouseBaseNoImage(houseBaseDTO);
            houseBase.setId(Integer.parseInt(houseBaseDTO.getId()));
            houseDao.saveOrUpdateHouseBaseByGuid(houseBase, guid);
        }
    }

    @Override
    @Transactional
    public List<HouseBaseDTO> findHouseBase(String currentPage) {
        List<HouseBase> houseBases = houseDao.findHouseBase(currentPage);
        List<HouseBaseDTO> houseBaseDTOs = HouseBaseDTO.toDTOs(houseBases);
        return houseBaseDTOs;
    }

    @Override
    @Transactional
    public List<HouseBaseDTO> findAllHouseBase(String type) {
        ProductType productType = ProductType.valueOf(type);
        List<HouseBase> houseBases = houseDao.findAllHouseBase(productType);
        List<HouseBaseDTO> houseBaseDTOs = HouseBaseDTO.toDTOs(houseBases);
        return houseBaseDTOs;
    }

    @Override
    @Transactional
    public List<HouseBaseDTO> findAllApartment() {
        List<HouseBase> houseBases = houseDao.findAllApartment();
        return HouseBaseDTO.toDTOs(houseBases);
    }


    @Override
    @Transactional
    public Object findTotalPage(Class clazz) {
        return houseDao.findTotalPage(clazz);
    }

    @Override
    @Transactional
    public HouseBaseDTO findHouseBaseByGuid(String guid) {
        HouseBase houseBase = houseDao.findByGuid(HouseBase.class, guid);
        HouseBaseDTO houseBaseDTO = HouseBaseDTO.toDTO(houseBase);
        return houseBaseDTO;
    }

    @Override
    @Transactional
    public void deleteHouseBaseImage(HouseBaseDTO houseBaseDTO) {
        for (MultipartFile m : houseBaseDTO.getImages()) {
            if (!"".equals(m.getOriginalFilename())) {
                HouseBase houseBase = houseBaseDTO.toHouseBase(houseBaseDTO);
                houseBase.setId(Integer.parseInt(houseBaseDTO.getId()));
                houseDao.deleteHouseBaseImage(houseBase);
            }
        }
    }

    @Override
    @Transactional
    public void deleteHouseBaseByGuid(String guid) {
        HouseBase houseBase = houseDao.findByGuid(HouseBase.class, guid);
        houseDao.deleteHouseBase(houseBase);
    }

    @Override
    @Transactional
    public void deleteUploadImageByGuid(String guid) {
        houseDao.deleteUploadImageByGuid(guid);
    }

    @Override
    @Transactional
    public List<BuildingType> findBuildingTypeByHouseBase(String guid) {
        HouseBase houseBase = houseDao.findByGuid(HouseBase.class, guid);
        List<BuildingType> buildingTypes = houseDao.findBuildingTypeByHouseBase(houseBase);
        return buildingTypes;
    }


    @Override
    @Transactional
    public List<HouseBase> findHouseBaseByTitle(String title) {
        return houseDao.findHouseBaseByTitle(title);
    }

    @Override
    @Transactional
    public List<HouseBaseImage> findHouseBaseImageByHouseBaseId(String houseBaseId) {
        return houseDao.findHouseBaseImageByHouseBaseId(houseBaseId);
    }

    @Override
    @Transactional
    public List<HouseBaseDTO>
    findHouseBaseByMoreCondition(String area, String price, String theme, String productType) {
        area = HouseBaseHandle.initAreaHql(area);
        price = HouseBaseHandle.initPriceHql(price);
        theme = HouseBaseHandle.initThemeHql(theme);
        productType = HouseBaseHandle.initProductType(productType);

        List<HouseBase> houseBases;
        if (StringUtils.isEmpty(area) && StringUtils.isEmpty(price) && StringUtils.isEmpty(theme)) {
            houseBases = houseDao.findHouseByProductType(productType);
        } else {
            houseBases = houseDao.findHouseBaseByMoreCondition(area, price, productType, theme);
        }
        List<HouseBaseDTO> houseBaseDTOs = HouseBaseDTO.toDTOs(houseBases);
        return houseBaseDTOs;
    }

    @Override
    @Transactional
    public BuildingTypeDTO findBuildingTypeDTOByGuid(String buildingTypeGuid) {
        BuildingType buildingType = houseDao.findBuildingTypeByGuid(buildingTypeGuid);
        BuildingTypeDTO buildingTypeDTO = BuildingTypeDTO.toDTO(buildingType);
        return buildingTypeDTO;
    }

    @Override
    @Transactional
    public void deleteBuildingTypeImageByGuid(String imageGuid) {
        UploadImage uploadImage = houseDao.findByGuid(UploadImage.class, imageGuid);
        houseDao.deleteBuildingTypeImageByGuid(uploadImage);
    }

    @Override
    @Transactional
    public void deleteBuildingTypeByGuid(String buildingTypeGuid) {
        BuildingType buildingType = houseDao.findByGuid(BuildingType.class, buildingTypeGuid);
        houseDao.deleteObject(buildingType);
    }

    @Override
    @Transactional
    public List<HouseBaseDTO> loadByParam(HouseParamDTO houseParamDTO) {
        List<HouseBaseDTO> houseBaseDTOs = houseDao.loadByParam(houseParamDTO);
        return null;
    }

    @Override
    @Transactional
    public void saveOrUpdateBannerForApp(BannerForAppDTO bannerForAppDTO) {

        List<MultipartFile> firstFiles = bannerForAppDTO.getFirstImages();
        MultipartFile secondFile = bannerForAppDTO.getSecondImage();

        BannerForApp bannerForApp = new BannerForApp();

        List<FirstBanners> firstImages = new ArrayList<>();

        for (MultipartFile file : firstFiles) {
            UploadImage image = ImageUtils.MultipartFileToUploadImage(file);
            firstImages.add(new FirstBanners(bannerForApp, image));
        }

        UploadImage secondImage = ImageUtils.MultipartFileToUploadImage(secondFile);

        bannerForApp.update(firstImages, secondImage);
        houseDao.saveOrUpdate(bannerForApp);

    }

    @Transactional
    public BannerForApp findBannerForApps() {
        List<BannerForApp> bannerForAppList = houseDao.findAll(BannerForApp.class);
        if (0 != bannerForAppList.size()) {
            return bannerForAppList.get(0);
        }
        return null;
    }

    @Override
    @Transactional
    public void deleteFirstBanner(String guid) {
        UploadImage uploadImage = houseDao.findByGuid(UploadImage.class, guid);
        FirstBanners firstBanners = houseDao.findFirstBanners(uploadImage).get(0);
        firstBanners.guid();
        houseDao.delete(firstBanners.guid(), FirstBanners.class);
    }

    @Override
    @Transactional
    public void upDataBannerForApp(BannerForAppDTO bannerForAppDTO) {
        MultipartFile secondFile = bannerForAppDTO.getSecondImage();
        List<MultipartFile> firstFiles = bannerForAppDTO.getFirstImages();
        List<UploadImage> firstImages = new ArrayList<>();
        if (!firstFiles.isEmpty()) {
            MultipartFile file = firstFiles.get(0);
            if (file.getSize() > 0) {
                firstImages = ImageUtils.resolveUploadImages(firstFiles);
            }
        }
        String guid = bannerForAppDTO.getGuid();
        BannerForApp bannerForApp = houseDao.findByGuid(BannerForApp.class, guid);
        updatForFirst(firstImages, bannerForApp);
        updateForSeond(secondFile, bannerForApp);
    }

    @Override
    @Transactional
    public void deleteImageForBanner(String imgGuid) {
        BannerForApp bannerForApp = houseDao.findSecondBannerByImage(imgGuid);
        bannerForApp.updateSecondBanner(null);
        houseDao.delete(imgGuid, UploadImage.class);
    }

    private void updateForSeond(MultipartFile secondFile, BannerForApp bannerForApp) {
        if (secondFile.getSize() > 0) {
            UploadImage secondImg = ImageUtils.MultipartFileToUploadImage(secondFile);
            bannerForApp.updateImage(secondImg);
        }
    }

    private void updatForFirst(List<UploadImage> firstImages, BannerForApp bannerForApp) {
        List<FirstBanners> firstBannerses = bannerForApp.firstBanners();
        if (!firstImages.isEmpty()) {
            for (UploadImage image : firstImages) {
                FirstBanners firstBanners = new FirstBanners(bannerForApp, image);
                firstBannerses.add(firstBanners);
            }
            bannerForApp.firstBanners().addAll(firstBannerses);
        } else {
            bannerForApp.updateImages(firstBannerses);
        }
    }

    @Override
    @Transactional
    public void saveOrUpdateAgreement(AgreementDTO agreementDTO) {
        String houseInfoGuid = agreementDTO.getHouseInfoguid();
        HouseInfo houseInfo = houseDao.findByGuid(HouseInfo.class, houseInfoGuid);
        Agreement agreement = AgreementDTO.toAgreement(agreementDTO, houseInfo);
        houseDao.deleteAgreementByHouseInfo(houseInfo);
        houseDao.saveOrUpdate(agreement);
    }

    @Override
    @Transactional
    public List<AgreementDTO> getAgreementDTOs() {
        List<Agreement> agreements = houseDao.findAll(Agreement.class);
        List<AgreementDTO> agreementDTOs = AgreementDTO.toDTOs(agreements);
        return agreementDTOs;
    }

    @Override
    @Transactional
    public AgreementDTO getAgreementDTOByGuid(String agreementGuid) {
        Agreement agreement = houseDao.findByGuid(Agreement.class, agreementGuid);
        AgreementDTO agreementDTO = AgreementDTO.toDTO(agreement);
        return agreementDTO;
    }

    @Override
    @Transactional
    public AgreementDTO getAgreementDTOByHouseInfoDTO(HouseInfoDTO houseInfoDTO) {
        HouseInfo houseInfo = houseDao.findByGuid(HouseInfo.class, houseInfoDTO.getGuid());
        Agreement agreement = houseDao.findAgreementByHouseInfo(houseInfo);
        AgreementDTO agreementDTO = new AgreementDTO();
        if (agreement != null) {
            agreementDTO = AgreementDTO.toDTO(agreement);

        }
        return agreementDTO;
    }

    @Override
    public Object findTotalPageByStatus(Class clazz, String status) {
        Object object;
        if (status.equals("ALL")) {
            object = houseDao.findTotalPage(clazz);
        } else {
            object = houseDao.findTotalPageByStatus(clazz, status);
        }
        return object;
    }

    @Override
    public void sort(int sort, String guid) {
        HouseBase houseBase = houseDao.findByGuid(HouseBase.class, guid);
        houseBase.initSort(sort);
    }

    @Override
    public void deleteUploadImageByGuidForHouseInfo(String imgGuid) {
        houseDao.deleteUploadImageByGuidForHouseInfo(imgGuid);
    }

    @Override
    public void deleteUploadHouseExtraFeeByGuid(String guid) {
        houseDao.deleteUploadHouseExtraFeeByGuid(guid);
    }

    @Override
    public List<HouseInfoDTO> houseInfoNoWeekTime() {
        List<HouseInfo> houseInfos = houseDao.findAll(HouseInfo.class);
        List<HouseInfo> houseInfos1 = houseDao.findAll(HouseInfo.class);
        List<HouseWeek> houseWeeks = houseDao.findAll(HouseWeek.class);
        for (HouseWeek houseWeek : houseWeeks) {
            for (HouseInfo houseInfo : houseInfos) {
                if (houseWeek.houseInfo() == houseInfo) {
                    houseInfos1.remove(houseInfo);
                }
            }
        }
        List<HouseInfoDTO> houseInfoDTOs = HouseInfoDTO.toDTOs(houseInfos1);
        return houseInfoDTOs;
    }

    @Override
    public List<HouseInfoDTO> getHouseInfoDTOsHaveWeek() {
        List<HouseInfo> houseInfos = houseDao.findAll(HouseInfo.class);
        List<HouseInfo> houseInfos1 = new ArrayList<>();
        for (HouseInfo houseInfo : houseInfos) {
            HouseWeek houseWeekH = houseWeekDao.findHouseWeekByWeek("黄金周", houseInfo);
            HouseWeek houseWeekW = houseWeekDao.findHouseWeekByWeek("旺季周", houseInfo);
            HouseWeek houseWeekP = houseWeekDao.findHouseWeekByWeek("平季周", houseInfo);
            HouseWeek houseWeekD = houseWeekDao.findHouseWeekByWeek("淡季周", houseInfo);
            if (houseWeekW != null && houseWeekP != null && houseWeekD != null && houseWeekH != null) {
                houseInfos1.add(houseInfo);
            }
        }
        List<HouseInfoDTO> houseInfoDTOs = HouseInfoDTO.toDTOs(houseInfos1);
        return houseInfoDTOs;
    }

    @Override
    public List<HouseInfoDTO> findhouseInfoByhouseBaseArea(String houseBaseArea) {
        List<HouseInfo> houseInfos = houseDao.findhouseInfoByhouseBaseArea(houseBaseArea);
        List<HouseInfoDTO> houseInfoDTOs = HouseInfoDTO.toDTOs(houseInfos);
        return houseInfoDTOs;
    }

    @Override
    public AssignmentDTO getAssignmentDTO(String assignmentguid) {
        AssignmentDTO assignmentDTO = AssignmentDTO.toDTO(houseDao.findByGuid(Assignment.class, assignmentguid));
        return assignmentDTO;
    }

    @Override
    @Transactional
    public Object updataEquipment(String guid, String name) {
        Object object = true;
        try {
            Equipment equipment = houseDao.findByGuid(Equipment.class, guid);
            equipment.updataName(name);
        } catch (Exception e) {
            object = false;
        }
        return object;
    }

    @Override
    @Transactional
    public Equipment addEquipment(String name, String type) {
        try {
            Equipment equipment = new Equipment(name, EquipmentType.valueOf(type));
            houseDao.saveOrUpdate(equipment);
            return equipment;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public String saveOrUpdateImage(MultipartFile filename) {
        UploadImage uploadImage = ImageUtils.MultipartFileToUploadImage(filename);
        houseDao.saveOrUpdate(uploadImage);
        return uploadImage.guid();
    }
}
